package com.base;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.conf.web.FileDel;
import com.constant.HandleEnum;
import com.exception.ServiceException;
import com.util.StringUtil;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Map;
@Slf4j
public  class BaseServiceImpl<REQ ,RES ,M extends BaseMapper<T>, T> extends ServiceImpl<M,T> implements BaseService<REQ, RES> {

    @Override
    public RES handle(REQ req) {
        String handle = "";
        try {
            Field declaredField = req.getClass().getDeclaredField(HandleEnum.HANDLE.getCode());
            declaredField.setAccessible(true);
             handle = (String) declaredField.get(req);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        HandleEnum handleEnum = HandleEnum.codeOf(handle);
        if (handleEnum == null) {
            throw new ServiceException("请传入handle");
        }
        RES res = null;
        switch (handleEnum) {
            case ADD:
                res = this.add(req);
                break;
            case DEL:
                res = this.del(req);
                break;
            case UPDATE:
                res = this.update(req);
                break;
            case QUERY:
                res = this.query(req);
                break;
            default:
                throw new ServiceException("handle传值不正确");

        }

        return res;
    }

    @Override
    public RES add(REQ req) {


        RES res = null;
        try {
            T t = this.instanceT();
           BeanUtil.copyProperties(req,t);
            Field crDate = t.getClass().getDeclaredField("crDate");
            Date now = new Date();
            if(crDate != null) {
                crDate.setAccessible(true);
                crDate.set(t, now);
            }
            try{

            Field moDate = t.getClass().getDeclaredField("moDate");
            if(moDate != null) {
                moDate.setAccessible(true);
                moDate.set(t,now);
            }}
            catch (Exception e){

            }
            save(t);
            res = this.instanceRES();
            BeanUtil.copyProperties(t,res);

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return res;
    }

    @Override
    public RES del(REQ req) {
        RES res = null;
        try {
            Field ids = req.getClass().getDeclaredField("id");
            ids.setAccessible(true);
            Object id = ids.get(req);

            if (StringUtil.isEmpty(id)) {
                throw new ServiceException("请传入id");
            }
            Class<?> idClass = id.getClass();
            if(idClass.equals(Integer.class)){

                this.removeById((Integer)id);
            }
            if(idClass.equals(Long.class)){

                this.removeById((Long)id);
            }
            if(idClass.equals(String.class)){
                this.removeById((String)id);
            }

            res = this.query(req);

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return res;
    }

    @Override
    public  RES update(REQ req) {
        RES res = null;
        try {
            T t = this.queryT(req);
            StringUtil.throwEmpty(t, "未查询到修改数据");
            BeanUtil.copyProperties(req, t);
            try {
                Field moDates = t.getClass().getDeclaredField("moDate");
                if(moDates!=null) {
                    moDates.setAccessible(true);
                    moDates.set(t, new Date());
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServiceException(e.getMessage());
            }
            saveOrUpdate(t);
            res = this.query(req);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return res;
    }

    @Override
    public RES query(REQ req) {
        RES res = null;
        try {

            T t = this.queryT(req);

            res = this.instanceRES();
            BeanUtil.copyProperties(t,res);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return res;
    }

    /**
     * 查询实体
     * @param req
     * @return
     */
    public T queryT(REQ req){
        T t = null;
        try {
            Field ids = req.getClass().getDeclaredField("id");
            ids.setAccessible(true);
           Object  id = ids.get(req);
            if (StringUtil.isEmpty(id)) {
                throw new ServiceException("请传入id");
            }
            Class<?> idClass = id.getClass();
            if(idClass.equals(Integer.class)){
                t = this.getById((Integer)id);
            }
            if(idClass.equals(Long.class)){
                t = this.getById((Long)id);
            }
            if(idClass.equals(String.class)){
                t = this.getById((String)id);
            }


        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return t;
    }

    /**
     * RES
     * @return
     */
    public RES instanceRES(){
        RES res = null;
        try {
            ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
            Type[] actualTypeArguments = ptype.getActualTypeArguments();
            Class clazz = (Class<RES>) ptype.getActualTypeArguments()[1];
            res = (RES) clazz.newInstance();
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return res;
    }

    /**
     * 实例T
     * @return
     */
    public T instanceT(){
        T t = null;
        try {
            ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
            Type[] actualTypeArguments = ptype.getActualTypeArguments();
            Class clazz = (Class<T>) ptype.getActualTypeArguments()[3];
            t = (T) clazz.newInstance();
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return t;
    }

    @Override
    public int countByField(String column, Object value) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(column,value);
        return this.count(queryWrapper);
    }
}
